<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>放大镜</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .box {
      display: flex;
      padding: 20px;
    }

    .left {
      width: 300px;
      height: 300px;
      margin-right: 20px;
      position: relative;
    }

    .cover {
      position: absolute;
      display: none;
      width: 100px;
      height: 100px;
      background-color: rgba(0, 0, 0, 0.5);
      pointer-events: none;
    }

    .right {
      width: 300px;
      height: 300px;
      overflow: hidden;
      position: relative;
      display: none;
    }

    .right img {
      width: 300%;
      height: 300%;
      position: absolute;
    }

    img {
      object-fit: cover;
      width: 100%;
      height: 100%;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="left">
      <img src="./img.jpg" alt="">
      <div class="cover"></div>
    </div>
    <div class="right">
      <img src="./img.jpg" alt="">
    </div>
  </div>
</body>
<script>
  const $ = (el) => document.querySelector(el)

  window.onload = () => {
    $('.left').onmousemove = move
    $('.left').onmouseenter = () => {
      $('.cover').style.display = 'block'
      $('.right').style.display = 'block'
    }
    $('.left').onmouseleave = () => {
      $('.cover').style.display = 'none'
      $('.right').style.display = 'none'
    }
  }

  function move(e) {
    const width = $('.cover').offsetWidth
    const height = $('.cover').offsetHeight

    let x = e.offsetX - width / 2
    let y = e.offsetY - height / 2

    const maxX = this.offsetWidth - width
    const maxY = this.offsetHeight - height

    $('.cover').style.left = x + 'px'
    $('.cover').style.top = y + 'px'

    $('.right img').style.left = -3 * x + 'px';
    $('.right img').style.top = -3 * y + 'px';
  }

  const clamp = (value, min, max) => Math.min(Math.max(value, min), max)
</script>

</html>